// Copyright 2007-2009 Comdiv (F. Sadykov) - http://code.google.com/u/fagim.sadykov/
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// MODIFICATIONS HAVE BEEN MADE TO THIS FILE


using System.IO;
using System.Web.Mvc;
using System.Xml.Linq;
using System.Xml.XPath;
using System.Xml.Xsl;

namespace MvcContrib.Comdiv.ViewEngines.Xslt{
    public class XsltView : IView{
        public XslCompiledTransform Transform { get; set; }
        public XsltArgumentList Arguments { get; set; }

        #region IView Members

        public void Render(ViewContext viewContext, TextWriter writer){
            IXPathNavigable nav = getXpathNavigable(viewContext.ViewData.Model);
            PrepareArguments(viewContext);
            Transform.Transform(nav, Arguments, writer);
        }

        #endregion

        private void PrepareArguments(ViewContext viewContext){
            Arguments = Arguments ?? new XsltArgumentList();
            foreach (var data in viewContext.ViewData){
                if (data.Value == null){
                    continue;
                }

                if (
                    (data.Value is string)
                    ||
                    (data.Value.GetType().IsValueType)
                    ||
                    (data.Value is XPathNodeIterator)
                    ||
                    (data.Value is XPathNavigator)
                    ||
                    (data.Value is XElement)
                    ){
                    object val = data.Value;
                    if (val is XElement){
                        val = new XPathDocument(new StringReader(val.ToString())).CreateNavigator().SelectSingleNode("/");
                    }
                    Arguments.RemoveParam(data.Key, "");
                    Arguments.AddParam(data.Key, "", val);
                }
                else{
                    Arguments.RemoveExtensionObject("param://" + data.Key);
                    Arguments.AddExtensionObject("param://" + data.Key, data.Value);
                }
            }
        }

        private IXPathNavigable getXpathNavigable(object xmlsource){
            if (xmlsource == null){
                return new XPathDocument(new StringReader("<__xml/>"));
            }
            if (xmlsource is IXPathNavigable){
                return (IXPathNavigable) xmlsource;
            }
            //strings and XElement
            return new XPathDocument(new StringReader(xmlsource.ToString()));
        }
    }
}